using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using WPCoco.Tasks;
using WPCoco.DataStrucure;

namespace WPCoco
{
    /// <summary>
    /// Scheduler that keep task running
    /// </summary>
    public class Scheduler : GameComponent
    {
        #region Singleton

        static Scheduler shared;
        /// <summary>
        /// Singleton class for the sheduler
        /// </summary>
        public static Scheduler Shared
        {
            get 
            {
                if (shared == null)
                    shared = new Scheduler(Coco.Shared.Game);
                return shared; 
            }
        }
        
        #endregion

        private Scheduler(Game game)
            : base(game)
        {

            
        }

        LinkedList<Task> tasks = new LinkedList<Task>();
        LinkedList<Task> news = new LinkedList<Task>();

        /// <summary>
        /// Total running task count
        /// </summary>
        public int RunningTaskCount { get { return tasks.Count; } }

        /// <summary>
        /// New tasks to be scheduled
        /// </summary>
        public int NewTaskCount { get { return news.Count; } }

        /// <summary>
        /// Schedule one task
        /// </summary>
        /// <param name="task"></param>
        public void AddTask(Task task) 
        {
            if (task == null) return;
            news.AddLast(task);
        }

        Set<object> removeOwners = new Set<object>();

        /// <summary>
        /// Add one object for removing all task linked to it
        /// </summary>
        /// <param name="owner"></param>
        public void RemoveFromOwner(object owner) 
        {
            removeOwners.Add(owner);
        }

        public override void Update(GameTime gameTime)
        {
            float time = (float)gameTime.TotalGameTime.TotalSeconds;

            LinkedListNode<Task> piv, temp;
            Task t;

            piv = tasks.First;
            while (piv != null)
            {
                t = piv.Value;
                temp = piv;
                piv = piv.Next;
                if (t.IsStoped || removeOwners.Contains(t.Owner))
                {
                    tasks.Remove(temp);
                }
            }

            piv = news.First;
            while (piv != null)
            {
                t = piv.Value;

                if (!t.IsStoped)
                {
                    t.StartTime = time;
                    t.Initialize();
                    tasks.AddLast(t);
                }

                piv = piv.Next;
            }
            news.Clear();

            piv = tasks.First;
            while (piv != null)
            {
                t = piv.Value;
                t.Update(time - t.StartTime);
                temp = piv;
                piv = piv.Next;
                if (t.HasEnded())
                {
                    t.Finish();
                    tasks.Remove(temp);
                }
            }

            removeOwners.Clear();
        }
    }
}
